package clustersimulator;
import java.util.Queue;

public class NetworkProcessor {

	/*
	 * List of clusters sorted by size
	 */
	protected ProcessingCluster[] processingClusters;

	public NetworkProcessor(ProcessingCluster[] newClusters) {
		if (newClusters.length < 1) {
			throw new IllegalArgumentException("No processing clusters provided to assigner.");
		}

		processingClusters = new ProcessingCluster[newClusters.length];
		processingClusters[0] = newClusters[0];
		int cursor;
		int end=0;
		for (int i=1; i < newClusters.length; i++) {
			for (cursor=0; cursor < i; cursor++) {
				if (newClusters[i].size() < processingClusters[cursor].size()) {
					break;
				}
			}

			// make room by shifting larger right
			for (int j=end; j >= cursor; j--) {
				processingClusters[j+1] = processingClusters[j];
			}

			processingClusters[cursor] = newClusters[i];
			end++;
		}
	}

	public void printClusters() {
		System.out.println("Cluster   Size   Available");
		for (int i=0; i < processingClusters.length; i++) {
			System.out.format("   %d       %d        %b%n", i, processingClusters[i].size(), processingClusters[i].isAvailable());
		}
	}

	public void assignJobs(Queue<Job> jobQueue, long clock) {
		Job nextJob = jobQueue.peek();
		Job assignee;
		int bestFitIndex;
		while (nextJob != null) {
			bestFitIndex = -1;
			for (int i=0; i < processingClusters.length; i++) {
				if (processingClusters[i].isAvailable()) {
					bestFitIndex = i;
				}
				if (bestFitIndex > -1 && processingClusters[bestFitIndex].size() >= nextJob.getADOC()) {
					break;
				}
			}

			if (bestFitIndex == -1) {
				break;
			} else {
				assignee = jobQueue.poll();
				assignee.setTimeAssigned(clock);
				processingClusters[bestFitIndex].assignJob(assignee);
			}

			nextJob = jobQueue.peek();
		}
	}

	public void processJobs(long clock) {
		for (int i=0; i<processingClusters.length; i++) {
			processingClusters[i].processJob(clock);
		}
	}

	public long totalIdleNodeCycles() {
		long total = 0;
		for (int i=0; i < processingClusters.length; i++) {
			total += processingClusters[i].getIdleNodeCycles();
		}
		return total;
	}

}
